home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 317 / asmsrc / input-sc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-20  |  11.0 KB  |  408 lines

  1. /* input_scrub.c - */
  2.  
  3. /* Copyright (C) 1987 Free Software Foundation, Inc.
  4.  
  5. This file is part of Gas, the GNU Assembler.
  6.  
  7. The GNU assembler is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Assembler General
  12. Public License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. the GNU Assembler, but only under the conditions described in the
  16. GNU Assembler General Public License.  A copy of this license is
  17. supposed to have been given to you along with the GNU Assembler
  18. so you can know your rights and responsibilities.  It should be
  19. in a file named COPYING.  Among other things, the copyright
  20. notice and this notice must be preserved on all copies.  */
  21.  
  22. #include "as.h"
  23. #include "read.h"
  24. #include "input-file.h"
  25.  
  26. /*
  27.  * O/S independent module to supply buffers of sanitised source code
  28.  * to rest of assembler. We get raw input data of some length.
  29.  * Also looks after line numbers, for e.g. error messages.
  30.  * This module used to do the sanitising, but now a pre-processor program
  31.  * (app) does that job so this module is degenerate.
  32.  * Now input is pre-sanitised, so we only worry about finding the
  33.  * last partial line. A buffer of full lines is returned to caller.
  34.  * The last partial line begins the next buffer we build and return to caller.
  35.  * The buffer returned to caller is preceeded by BEFORE_STRING and followed
  36.  * by AFTER_STRING. The last character before AFTER_STRING is a newline.
  37.  */
  38.  
  39. /*
  40.  * We expect the following sanitation has already been done.
  41.  *
  42.  * No comments, reduce a comment to a space.
  43.  * Reduce a tab to a space unless it is 1st char of line.
  44.  * All multiple tabs and spaces collapsed into 1 char. Tab only
  45.  *   legal if 1st char of line.
  46.  * # line file statements converted to .line x;.file y; statements.
  47.  * Escaped newlines at end of line: remove them but add as many newlines
  48.  *   to end of statement as you removed in the middle, to synch line numbers.
  49.  */
  50.  
  51. #define BEFORE_STRING ("\n")
  52. #define AFTER_STRING (" ")    /* bcopy of 0 chars might choke. */
  53. #define BEFORE_SIZE (1)
  54. #define AFTER_SIZE  (1)
  55.  
  56. static char *    buffer_start;    /* -> 1st char of full buffer area. */
  57. static char *    partial_where;    /* -> after last full line in buffer. */
  58. static int    partial_size;    /* >=0. Number of chars in partial line in buffer. */
  59.  
  60. #ifdef atarist
  61. static char    save_source [2];    /* odd num fucks alignment? */
  62. #else
  63. static char    save_source [AFTER_SIZE];
  64. #endif
  65.                 /* Because we need AFTER_STRING just after last */
  66.                 /* full line, it clobbers 1st part of partial */
  67.                 /* line. So we preserve 1st part of partial */
  68.                 /* line here. */
  69. static int    buffer_length;    /* What is the largest size buffer that */
  70.                 /* input_file_give_next_buffer() could */
  71.                 /* return to us? */
  72.  
  73.  
  74.  
  75. /*
  76. We never have more than one source file open at once.
  77. We may, however, read more than 1 source file in an assembly.
  78. NULL means we have no file open right now.
  79. */
  80.  
  81.  
  82. /*
  83. We must track the physical file and line number for error messages.
  84. We also track a "logical" file and line number corresponding to (C?)
  85. compiler source line numbers.
  86. Whenever we open a file we must fill in physical_input_file. So if it is NULL
  87. we have not opened any files yet.
  88. */
  89.  
  90. static
  91. char *        physical_input_file,
  92.      *        logical_input_file;
  93.  
  94.  
  95.  
  96. typedef unsigned int line_numberT;    /* 1-origin line number in a source file. */
  97.                 /* A line ends in '\n' or eof. */
  98.  
  99. static
  100. line_numberT    physical_input_line,
  101.         logical_input_line;
  102.  
  103. void
  104. input_scrub_begin ()
  105. {
  106.   know( strlen(BEFORE_STRING) == BEFORE_SIZE );
  107.   know( strlen( AFTER_STRING) ==  AFTER_SIZE );
  108.  
  109.   input_file_begin ();
  110.  
  111.   buffer_length = input_file_buffer_size ();
  112.  
  113.   buffer_start = xmalloc ((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
  114.   bcopy (BEFORE_STRING, buffer_start, (int)BEFORE_SIZE);
  115.  
  116.   /* Line number things. */
  117.   logical_input_line = 0;
  118.   logical_input_file = (char *)NULL;
  119.   physical_input_file = NULL;    /* No file read yet. */
  120.   do_scrub_begin();
  121. }
  122.  
  123. void
  124. input_scrub_end ()
  125. {
  126.   input_file_end ();
  127. }
  128.  
  129. char *                /* Return start of caller's part of buffer. */
  130. input_scrub_new_file (filename)
  131.      char *    filename;
  132. {
  133.   input_file_open (filename, !flagseen['f']);
  134.   physical_input_file = filename[0] ? filename : "{standard input}";
  135.   physical_input_line = 0;
  136.  
  137.   partial_size = 0;
  138.   return (buffer_start + BEFORE_SIZE);
  139. }
  140.  
  141. char *
  142. input_scrub_next_buffer (bufp)
  143. char **bufp;
  144. {
  145.   register char *    limit;    /* -> just after last char of buffer. */
  146.   char *p;
  147.   char *out_string;
  148.   int out_length;
  149.   static char *save_buffer = 0;
  150.   extern int preprocess;
  151.   extern char *buffer;
  152.  
  153.   if(preprocess) {
  154.     if(save_buffer) {
  155.       *bufp = save_buffer;
  156.       save_buffer = 0;
  157.     }
  158.     limit = input_file_give_next_buffer(buffer_start+BEFORE_SIZE);
  159.     if (!limit) {
  160.       partial_where = 0;
  161.       if(partial_size)
  162.         as_warn("Partial line at end of file ignored");
  163.       return partial_where;
  164.     }
  165.  
  166.     if(partial_size)
  167.       bcopy(save_source, partial_where,(int)AFTER_SIZE);
  168.     do_scrub(partial_where,partial_size,buffer_start+BEFORE_SIZE,limit-(buffer_start+BEFORE_SIZE),&out_string,&out_length);
  169. /*
  170. fprintf(stderr,"after scrub: source %X(%d) target %X(%d)\n",
  171.     buffer_start+BEFORE_SIZE, (limit - (buffer_start + BEFORE_SIZE)),
  172.     out_string, out_length);
  173. fprintf(stderr, "'%.*s'\n", 
  174.     limit - (buffer_start+BEFORE_SIZE),
  175.     buffer_start+BEFORE_SIZE);
  176. fprintf(stderr, "'%.*s'\n", out_length, out_string);
  177. */
  178.     limit=out_string + out_length;
  179.     for(p=limit;*--p!='\n';)
  180.       ;
  181.     p++;
  182. /* .. jrd
  183.     if(p<=buffer_start+BEFORE_SIZE) */
  184.     if(p<=out_string)
  185. {
  186. fprintf(stderr, "bogon alert: p=%X, start=%X\n", p,buffer_start+BEFORE_SIZE);
  187.       as_fatal("Source line too long.  Please change file '%s' and re-make the assembler.",__FILE__);
  188. }
  189.     partial_where = p;
  190.     partial_size = limit-p;
  191.     bcopy(partial_where, save_source,(int)AFTER_SIZE);
  192.     bcopy(AFTER_STRING, partial_where, (int)AFTER_SIZE);
  193.  
  194.     save_buffer = *bufp;
  195.     *bufp = out_string;
  196.  
  197.     return partial_where;
  198.   }
  199.  
  200.   /* We're not preprocessing.  Do the right thing */
  201.     
  202.   if (partial_size)
  203.     {
  204.       bcopy (partial_where, buffer_start + BEFORE_SIZE, (int)partial_size);
  205.       bcopy (save_source, buffer_start + BEFORE_SIZE, (int)AFTER_SIZE);
  206.     }
  207.   limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size);
  208.   if (limit)
  209.     {
  210.       register char *    p;    /* Find last newline. */
  211.  
  212.       for (p = limit;   * -- p != '\n';   )
  213.     {
  214.     }
  215.       ++ p;
  216.       if (p <= buffer_start + BEFORE_SIZE)
  217.     {
  218.       as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__);
  219.     }
  220.       partial_where = p;
  221.       partial_size = limit - p;
  222.       bcopy (partial_where, save_source,  (int)AFTER_SIZE);
  223.       bcopy (AFTER_STRING, partial_where, (int)AFTER_SIZE);
  224.     }
  225.   else
  226.     {
  227.       partial_where = 0;
  228.       if (partial_size > 0)
  229.     {
  230.       as_warn( "Partial line at end of file ignored" );
  231.     }
  232.     }
  233.   return (partial_where);
  234. }
  235.  
  236. /*
  237.  * The remaining part of this file deals with line numbers, error
  238.  * messages and so on.
  239.  */
  240.  
  241.  
  242. int
  243. seen_at_least_1_file ()        /* TRUE if we opened any file. */
  244. {
  245.   return (physical_input_file != NULL);
  246. }
  247.  
  248. void
  249. bump_line_counters ()
  250. {
  251.   ++ physical_input_line;
  252.   ++ logical_input_line;
  253. }
  254.  
  255. /*
  256.  *            new_logical_line()
  257.  *
  258.  * Tells us what the new logical line number and file are.
  259.  * If the line_number is <0, we don't change the current logical line number.
  260.  * If the fname is NULL, we don't change the current logical file name.
  261.  */
  262. void
  263. new_logical_line (fname, line_number)
  264.      char *    fname;        /* DON'T destroy it! We point to it! */
  265.      int    line_number;
  266. {
  267.   if ( fname )
  268.     {
  269.       logical_input_file = fname;
  270.     }
  271.   if ( line_number >= 0 )
  272.     {
  273.       logical_input_line = line_number;
  274.     }
  275. }
  276.  
  277. /*
  278.  *            a s _ w h e r e ( )
  279.  *
  280.  * Write a line to stderr locating where we are in reading
  281.  * input source files.
  282.  * As a sop to the debugger of AS, pretty-print the offending line.
  283.  */
  284. void
  285. as_where()
  286. {
  287.   char *p;
  288.   line_numberT line;
  289.  
  290.   if (physical_input_file)
  291.     {                /* we tried to read SOME source */
  292.       if (input_file_is_open())
  293.     {            /* we can still read lines from source */
  294. #ifdef DONTDEF
  295.       fprintf (stderr," @ physical line %ld., file \"%s\"",
  296.            (long) physical_input_line, physical_input_file);
  297.       fprintf (stderr," @ logical line %ld., file \"%s\"\n",
  298.            (long) logical_input_line, logical_input_file);
  299.       (void)putc(' ', stderr);
  300.       as_howmuch (stderr);
  301.       (void)putc('\n', stderr);
  302. #else
  303.         p = logical_input_file ? logical_input_file : physical_input_file;
  304.         line = logical_input_line ? logical_input_line : physical_input_line;
  305.         fprintf(stderr,"%s:%u:", p, line);
  306. #endif
  307.     }
  308.       else
  309.     {
  310. #ifdef DONTDEF
  311.       fprintf (stderr," After reading source.\n");
  312. #else
  313.     p = logical_input_file ? logical_input_file : physical_input_file;
  314.     line = logical_input_line ? logical_input_line : physical_input_line;
  315.     fprintf (stderr,"%s:%u:", p, line);
  316. #endif
  317.     }
  318.     }
  319.   else
  320.     {
  321. #ifdef DONTDEF
  322.       fprintf (stderr," Before reading source.\n");
  323. #else
  324. #endif
  325.     }
  326. }
  327.  
  328.  
  329.  
  330. /*
  331.  *            a s _ p e r r o r
  332.  *
  333.  * Like perror(3), but with more info.
  334.  */
  335. void
  336. as_perror(gripe, filename)
  337.      char *    gripe;        /* Unpunctuated error theme. */
  338.      char *    filename;
  339. {
  340.   extern int errno;        /* See perror(3) for details. */
  341.   extern int sys_nerr;
  342.   extern char * sys_errlist[];
  343.  
  344.   fprintf (stderr,"as:file(%s) %s! ",
  345.        filename, gripe
  346.        );
  347.   if (errno > sys_nerr)
  348.     {
  349.       fprintf (stderr, "Unknown error #%d.", errno);
  350.     }
  351.   else
  352.     {
  353.       fprintf (stderr, "%s.", sys_errlist [errno]);
  354.     }
  355.   (void)putc('\n', stderr);
  356.   errno = 0;            /* After reporting, clear it. */
  357.   if (input_file_is_open())    /* RMS says don't mention line # if not needed. */
  358.     {
  359.       as_where();
  360.     }
  361. }
  362.  
  363. /*
  364.  *            a s _ h o w m u c h ( )
  365.  *
  366.  * Output to given stream how much of line we have scanned so far.
  367.  * Assumes we have scanned up to and including input_line_pointer.
  368.  * No free '\n' at end of line.
  369.  */
  370. void
  371. as_howmuch (stream)
  372.      FILE * stream;        /* Opened for write please. */
  373. {
  374.   register    char *    p;    /* Scan input line. */
  375.   /* register    char    c; JF unused */
  376.  
  377.   for (p = input_line_pointer - 1;   * p != '\n';   --p)
  378.     {
  379.     }
  380.   ++ p;                /* p -> 1st char of line. */
  381.   for (;  p <= input_line_pointer;  p++)
  382.     {
  383.       /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
  384.       /* c = *p & 0xFF; JF unused */
  385.       as_1_char (*p, stream);
  386.     }
  387. }
  388.  
  389. static
  390. as_1_char (c,stream)
  391.      unsigned char c;
  392.      FILE *    stream;
  393. {
  394.   if ( c > 127 )
  395.     {
  396.       (void)putc( '%', stream);
  397.       c -= 128;
  398.     }
  399.   if ( c < 32 )
  400.     {
  401.       (void)putc( '^', stream);
  402.       c += '@';
  403.     }
  404.   (void)putc( c, stream);
  405. }
  406.  
  407. /* end: input_scrub.c */
  408.